package com.ct.application.shipping.service.impl;
import com.ct.application.shipping.model.vo.ChuanYuanVO;
import com.google.common.collect.Lists;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ct.application.shipping.model.po.ChuanYuanDiaoPeiJieTiSavePO;
import com.ct.application.shipping.model.po.ChuanYuanDiaoPeiSearchPO;
import com.ct.application.shipping.model.po.ChuanYuanDiaoPeiShangChuanSavePO;
import com.ct.application.shipping.model.po.ChuanYuanDiaoPeiXiaChuanSavePO;
import com.ct.application.shipping.model.vo.ChuanYuanDiaoPeiJieVO;
import com.ct.application.shipping.model.vo.ChuanYuanDiaoPeiVO;
import com.ct.application.shipping.model.vo.ChuanYuanZhiWeiVO;
import com.ct.application.shipping.service.*;
import com.ct.repository.commons.BaseServiceImpl;
import com.ct.shipping.mapper.ChuanYuanDiaoPeiMapper;
import com.ct.shipping.orm.*;
import com.ct.utils.date.DateUtils;
import com.ct.utils.date.TmDateUtil;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 船员调配 服务实现类
 * </p>
 *
 * @author carlo
 */
@Service
public class ChuanYuanDiaoPeiServiceImpl extends BaseServiceImpl<ChuanYuanDiaoPeiMapper, ChuanYuanDiaoPeiDO>
        implements ChuanYuanDiaoPeiService {

    @Resource
    private ChuanBoXinXiService chuanBoXinXiService;
    @Resource
    private ChuanYuanKuService chuanYuanKuService;
    @Resource
    private ChuanYuanChuQinService chuanYuanChuQinService;
    @Resource
    private ChuanBoZhiWeiService chuanBoZhiWeiService;


    /**
     * 保存船舶和职位关联的数据
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean saveChuanYuanDiaoPei(List<ChuanBoXinXiZhiWeiDO> chuanBoXinXiZhiWeiDOList) {
        if (chuanBoXinXiZhiWeiDOList == null || chuanBoXinXiZhiWeiDOList.size() == 0) {
            return false;
        }
        Long xinXiId = chuanBoXinXiZhiWeiDOList.get(0).getXinXiId();
        ChuanBoXinXiDO chuanBoXinXiDO = chuanBoXinXiService.getById(xinXiId);
        List<Long> zhiWeiIds = chuanBoXinXiZhiWeiDOList.stream().map(ChuanBoXinXiZhiWeiDO::getZhiWeiId)
                .collect(Collectors.toList());
        Map<Long, String> zhiWeiMap = chuanBoZhiWeiService.lambdaQuery()
                .in(ChuanBoZhiWeiDO::getId, zhiWeiIds)
                .list()
                .stream().collect(Collectors.toMap(ChuanBoZhiWeiDO::getId, ChuanBoZhiWeiDO::getZhiWeiMing));
        chuanBoXinXiZhiWeiDOList.forEach(item->{
            item.setChuanBoMing(chuanBoXinXiDO.getZhongWenMing());
            item.setZhiWeiMing(zhiWeiMap.getOrDefault(item.getZhiWeiId(),""));
        });

        /**
         * 1.根据船舶id筛选出调配数据。然后把调配数据进行分组，职位作为key，调配数据集合作为value
         *      若调配数据为空，则 根据职位数量，新增对应的调配数据。
         *      若调配数据不为空，往下执行第2点
         * 2.遍历船舶配置的职位数组:
         *      职位数量 > 调配数据集合的大小 则 新增多出数量的调配数据
         *      职位数量 = 调配数据集合的大小 则 跳过
         *      职位数量 < 调配数据集合的大小 则 需要删除多余的调配数据。删除判断逻辑是: 在船人员/接替人员/在船人员上船日期 三个
         *      字段若其中一个有值，不能删除。 三个字段全部是空的，可以删除。
         */
        List<ChuanYuanDiaoPeiDO> chuanYuanDiaoPeiDOList = this.lambdaQuery().eq(ChuanYuanDiaoPeiDO::getXinXiId, xinXiId).list();
        if (chuanYuanDiaoPeiDOList == null || chuanYuanDiaoPeiDOList.size() == 0) {
            //若调配数据为空，则 根据职位数量，新增对应的调配数据。
            for (ChuanBoXinXiZhiWeiDO chuanBoXinXiZhiWeiDO : chuanBoXinXiZhiWeiDOList) {
                String chuanBoMing = chuanBoXinXiZhiWeiDO.getChuanBoMing();//船舶名称
                String zhiWeiMing = chuanBoXinXiZhiWeiDO.getZhiWeiMing();//职位名称
                Integer shuLiang = chuanBoXinXiZhiWeiDO.getShuLiang();//职位数量
                if (shuLiang > 0) {
                    for (Integer i = 0; i < shuLiang; i++) {
                        ChuanYuanDiaoPeiDO saveDiaoPei = new ChuanYuanDiaoPeiDO();
                        saveDiaoPei.setXinXiId(xinXiId);
                        saveDiaoPei.setChuanBoMing(chuanBoMing);
                        saveDiaoPei.setZhiWei(zhiWeiMing);
                        saveDiaoPei.insert();
                    }
                }
            }
        } else {
            //把调配数据进行分组，职位作为key，调配数据集合作为value
            Map<String, List<ChuanYuanDiaoPeiDO>> diaoPeiDOMap = chuanYuanDiaoPeiDOList.stream().collect(Collectors.groupingBy(ChuanYuanDiaoPeiDO::getZhiWei));

            /** 遍历船舶配置的职位数组:
             职位数量 > 调配数据集合的大小 则 新增多出数量的调配数据
             职位数量 = 调配数据集合的大小 则 跳过
             职位数量 < 调配数据集合的大小 则 需要删除多余的调配数据。删除判断逻辑是: 离任人员/在船人员/接替人员
             三个字段若其中一个有值，不能删除。 三个字段全部是空的，可以删除。*/
            for (ChuanBoXinXiZhiWeiDO chuanBoXinXiZhiWeiDO : chuanBoXinXiZhiWeiDOList) {
                String chuanBoMing = chuanBoXinXiZhiWeiDO.getChuanBoMing();//船舶名称
                String zhiWeiMing = chuanBoXinXiZhiWeiDO.getZhiWeiMing();//职位名称
                Integer shuLiang = chuanBoXinXiZhiWeiDO.getShuLiang();//职位数量

                List<ChuanYuanDiaoPeiDO> diaoPeiDOList = diaoPeiDOMap.get(zhiWeiMing);
                if (diaoPeiDOList == null) {
                    diaoPeiDOList = new ArrayList<>();
                }
                //职位数量 > 调配数据集合的大小 则 新增多出数量的调配数据
                if (shuLiang > diaoPeiDOList.size()) {
                    int duoChu = shuLiang - diaoPeiDOList.size();
                    for (Integer i = 0; i < duoChu; i++) {
                        ChuanYuanDiaoPeiDO saveDiaoPei = new ChuanYuanDiaoPeiDO();
                        saveDiaoPei.setXinXiId(xinXiId);
                        saveDiaoPei.setChuanBoMing(chuanBoMing);
                        saveDiaoPei.setZhiWei(zhiWeiMing);
                        saveDiaoPei.insert();
                    }
                }
                //职位数量 < 调配数据集合的大小
                if (shuLiang < diaoPeiDOList.size()) {
                    int duoChu = diaoPeiDOList.size() - shuLiang;
                    for (ChuanYuanDiaoPeiDO diaoPeiDO : diaoPeiDOList) {
                        if (StringUtils.isNotEmpty(diaoPeiDO.getZaiChuanChuanYuanMing())
                                || StringUtils.isNotEmpty(diaoPeiDO.getJieTiChuanYuanMing())
                                || StringUtils.isNotEmpty(diaoPeiDO.getLiRenChuanYuanMing())
                        ) {
                            continue;
                        }
                        diaoPeiDO.deleteById();
                        duoChu = duoChu - 1;
                        if (duoChu == 0) {
                            break;
                        }
                    }
                }
            }
        }
        return true;
    }




    /**
     * 查询船舶对应的调配数据
     */
    public List<ChuanYuanDiaoPeiVO> findChuanYuanDiaoPei(ChuanYuanDiaoPeiSearchPO searchPO) {
        Long xinXiId = searchPO.getXinXiId();
        String chaXunRiQiStr = searchPO.getShangChuanRiQi();
        List<ChuanYuanDiaoPeiVO> chuanYuanDiaoPeiVOS = new ArrayList<>();
        Date chaXunRiQiDate = DateUtils.stringToDate(chaXunRiQiStr);
        Date currentDate = new Date();
        if (currentDate.before(chaXunRiQiDate)) {
            throw new RuntimeException("查询日期不能在今天之后");
        }

        List<ChuanYuanDiaoPeiDO> chuanYuanDiaoPeiList = new ArrayList<>();
        //日期查询参数 是今天的话，排除已经下船的数据
        String d1 = TmDateUtil.dateToString(chaXunRiQiDate, "yyyy-MM-dd");
        String d2 = TmDateUtil.dateToString(currentDate, "yyyy-MM-dd");
        if (d1.equals(d2)) {
            chuanYuanDiaoPeiList = this.lambdaQuery()
                    .eq(ChuanYuanDiaoPeiDO::getXinXiId, xinXiId)
                    .isNull(ChuanYuanDiaoPeiDO::getXiaChuanRiQi)
                    .list();
            if (chuanYuanDiaoPeiList.size() == 0) {
                return chuanYuanDiaoPeiVOS;
            }
        } else {
            Date chaXunRiQiEndDate = DateUtils.getEndDate(chaXunRiQiDate);
            chuanYuanDiaoPeiList = this.lambdaQuery()
                    .eq(ChuanYuanDiaoPeiDO::getXinXiId, xinXiId)
                    .le(ChuanYuanDiaoPeiDO::getShangChuanRiQi, chaXunRiQiEndDate)
                    .and(w->{
                        w.isNull(ChuanYuanDiaoPeiDO::getXiaChuanRiQi)
                                .or()
                                .gt(ChuanYuanDiaoPeiDO::getXiaChuanRiQi, chaXunRiQiEndDate);
                    })
                    .list();
            if (chuanYuanDiaoPeiList.size() == 0) {
                return chuanYuanDiaoPeiVOS;
            }
        }

        List<ChuanBoZhiWeiDO> zhiWeiDOList = chuanBoZhiWeiService.list();
        Map<String, Integer> zhiWeiPaixuMap = zhiWeiDOList.stream()
                .collect(Collectors.toMap(ChuanBoZhiWeiDO::getZhiWeiMing, ChuanBoZhiWeiDO::getXuHao));

        chuanYuanDiaoPeiVOS = chuanYuanDiaoPeiList.stream().map(chuanYuanDiaoPei -> {
            ChuanYuanDiaoPeiVO chuanYuanDiaoPeiVO = new ChuanYuanDiaoPeiVO();
            BeanUtils.copyProperties(chuanYuanDiaoPei,chuanYuanDiaoPeiVO);
            String zhiWei = chuanYuanDiaoPei.getZhiWei();
            Integer xuHao = zhiWeiPaixuMap.getOrDefault(zhiWei,0);
            chuanYuanDiaoPeiVO.setXuHao(xuHao);

            String liChuanShenQingCanShu = chuanYuanDiaoPei.getLiChuanShenQingCanShu();
            if(StringUtils.isNotEmpty(liChuanShenQingCanShu)){
                chuanYuanDiaoPeiVO.setLiChuanShenQingDO(JSON.parseObject(liChuanShenQingCanShu, LiChuanShenQingDO.class));
            }
            String diaoLingCanShu = chuanYuanDiaoPei.getDiaoLingCanShu();
            if(StringUtils.isNotEmpty(diaoLingCanShu)){
                chuanYuanDiaoPeiVO.setDiaoLingDO(JSON.parseObject(diaoLingCanShu, ChuanYuanDiaoLingDO.class));
            }
            return chuanYuanDiaoPeiVO;
        })
        // 添加排序操作
        .sorted(Comparator.comparing(ChuanYuanDiaoPeiVO::getXuHao))
        .collect(Collectors.toList());

        return chuanYuanDiaoPeiVOS;
    }

    /**
     * 根据调配面板查询《离船申请/调令》对应的职位及职位下的船员
     */
    public List<ChuanYuanZhiWeiVO> getChuanYuanList(Long xinXiId,String leixing) {
        List<ChuanYuanZhiWeiVO> chuanYuanZhiWeiVOs = new ArrayList<>();
        List<ChuanYuanDiaoPeiDO> chuanYuanDiaoPeiDOList = this.lambdaQuery()
                .eq(ChuanYuanDiaoPeiDO::getXinXiId, xinXiId)
                .isNull("离船".equals(leixing),ChuanYuanDiaoPeiDO::getLiChuanShenQingCanShu)
                .isNull("调令".equals(leixing),ChuanYuanDiaoPeiDO::getDiaoLingCanShu)
                .list();
        if (chuanYuanDiaoPeiDOList.size() == 0) {
            throw new RuntimeException("该船舶下的职位暂无数据");
        }
        ChuanYuanDiaoPeiDO chuanYuanDiaoPeiDO = chuanYuanDiaoPeiDOList.get(0);

        Map<String, List<ChuanYuanVO>> zhiweimap = chuanYuanDiaoPeiDOList.stream()
                .filter(item -> item.getZaiChuanChuanYuanId()>0)
                .map(item ->{
                    ChuanYuanVO chuanYuanVO = new ChuanYuanVO();
                    chuanYuanVO.setChuanYuanId(item.getZaiChuanChuanYuanId());
                    chuanYuanVO.setChuanYuanMing(item.getZaiChuanChuanYuanMing());
                    chuanYuanVO.setZhiWei(item.getZhiWei());
                    return chuanYuanVO;
                })
                .collect(Collectors.groupingBy(ChuanYuanVO::getZhiWei));

        for (String key : zhiweimap.keySet()) {
            List<ChuanYuanVO> chuanYuanVOS = zhiweimap.get(key);
            ChuanYuanZhiWeiVO chuanYuanZhiWeiVO = new ChuanYuanZhiWeiVO();
            chuanYuanZhiWeiVO.setZhiWei(key);
            chuanYuanZhiWeiVO.setXinXiId(chuanYuanDiaoPeiDO.getXinXiId());
            chuanYuanZhiWeiVO.setChuanBoMing(chuanYuanDiaoPeiDO.getChuanBoMing());
            chuanYuanZhiWeiVO.setChuanYuanVOS(chuanYuanVOS);
            chuanYuanZhiWeiVOs.add(chuanYuanZhiWeiVO);
        }
        return chuanYuanZhiWeiVOs;
    }



    @Override
    public ChuanYuanDiaoPeiVO getChuanYuanDiaoPei(Long id) {
        ChuanYuanDiaoPeiVO chuanYuanDiaoPeiVO = new ChuanYuanDiaoPeiVO();
        ChuanYuanDiaoPeiDO diaoPeiDO = getById(id);
        BeanUtils.copyProperties(diaoPeiDO, chuanYuanDiaoPeiVO);
        String shangChuanCanShu = diaoPeiDO.getShangChuanCanShu();
        if(StringUtils.isNotEmpty(shangChuanCanShu)) {
            ChuanYuanDiaoPeiShangChuanSavePO shangChuanSave = JSON.parseObject(shangChuanCanShu, ChuanYuanDiaoPeiShangChuanSavePO.class);
            chuanYuanDiaoPeiVO.setJianRenZhiWu(shangChuanSave.getJianRenZhiWu());            //设置 兼任职务
            chuanYuanDiaoPeiVO.setRenZhiShuoMing(shangChuanSave.getRenZhiShuoMing());        //设置 任职说明
            chuanYuanDiaoPeiVO.setShangChuanRiQi(shangChuanSave.getShangChuanRiQi());        //设置 上船日期
            chuanYuanDiaoPeiVO.setShangChuanChuQin(shangChuanSave.getShangChuanChuQin());    //设置 上船当天出勤(天)
            chuanYuanDiaoPeiVO.setShangChuanYuanShenFenHao(shangChuanSave.getShangChuanYuanShenFenHao()); //设置 上船船员身份号
            chuanYuanDiaoPeiVO.setShangChuanYuanShouJiHao(shangChuanSave.getShangChuanYuanShouJiHao());   //设置 上船船员手机号
        }
        return chuanYuanDiaoPeiVO;
    }

    /**
     * 上船
     */
    @Transactional(rollbackFor = Exception.class)
    public void shangChuan(ChuanYuanDiaoPeiShangChuanSavePO shangChuanSavePO) {
        Long id = shangChuanSavePO.getId();     //船员调配数据id
        if (id == null) {
            throw new RuntimeException("船员调配数据id参数不能为空");
        }
        ChuanYuanDiaoPeiDO diaoPeiDO = this.getById(id);
        if (diaoPeiDO == null) {
            throw new RuntimeException("查无此调配数据");
        }
        Long shangChuanChuanYuanId = shangChuanSavePO.getShangChuanChuanYuanId();//上船船员id
        if (shangChuanChuanYuanId == null) {
            throw new RuntimeException("上船船员id参数不能为空");
        }
        ChuanYuanKuDO shangChuanChuanYuan = chuanYuanKuService.getById(shangChuanChuanYuanId);
        if (shangChuanChuanYuan == null) {
            throw new RuntimeException("查无此上船船员数据");
        }
        ChuanYuanDiaoPeiDO chuanYuanDiaoPeiDO = this.lambdaQuery()
                .and(w -> {
                    w.eq(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanId, shangChuanChuanYuanId)
                            .or()
                            .eq(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId, shangChuanChuanYuanId);
                })
                .last(" limit 1 ")
                .one();
        if (chuanYuanDiaoPeiDO != null) {
            String chuanBoMing = chuanYuanDiaoPeiDO.getChuanBoMing();
            String zhiWei = chuanYuanDiaoPeiDO.getZhiWei();
            String zhuangtai = chuanYuanDiaoPeiDO.getZaiChuanChuanYuanId() > 0 ? "任职" : "接替";
            throw new RuntimeException("该船员已在船舶:《"+chuanBoMing+"》上的《"+zhiWei+"》职位上进行"+zhuangtai);
        }

        Long xinXiId = diaoPeiDO.getXinXiId();
        ChuanBoXinXiDO chuanBoXinXiDO = chuanBoXinXiService.getById(xinXiId);
        String zhiWei = diaoPeiDO.getZhiWei();                           //获取职位
        String shangChuanChuQin = chuanBoXinXiDO.getShangChuanChuQin();  //上船工作时间(天) 出勤
        String xiaChuanChuQin = chuanBoXinXiDO.getXiaChuanChuQin();      //下船当天出勤(天)

        shangChuanSavePO.setZhiWei(zhiWei);                                             //设置 职位
        shangChuanSavePO.setShangChuanChuQin(shangChuanChuQin);                         //设置 上船当天出勤
        shangChuanSavePO.setShangChuanChuanYuanId(shangChuanChuanYuan.getId());         //设置 上船船员id
        shangChuanSavePO.setShangChuanChuanYuanMing(shangChuanChuanYuan.getXingMing()); //设置 上船船员名字
        shangChuanSavePO.setShangChuanYuanShenFenHao(shangChuanChuanYuan.getShenFenHao()); //设置 上船船员身份号
        shangChuanSavePO.setShangChuanYuanShouJiHao(shangChuanChuanYuan.getShouJiHao());   //设置 上船船员手机号

        /*新增 船员出勤 数据*/
        ChuanYuanChuQinDO chuanYuanChuQinDO = new ChuanYuanChuQinDO();
        chuanYuanChuQinDO.setXinXiId(xinXiId);
        chuanYuanChuQinDO.setChuanBoMing(chuanBoXinXiDO.getZhongWenMing());
        chuanYuanChuQinDO.setChuanYuanId(shangChuanChuanYuan.getId());
        chuanYuanChuQinDO.setChuanYuanMing(shangChuanChuanYuan.getXingMing());
        chuanYuanChuQinDO.setChuanYuanShenFenHao(shangChuanChuanYuan.getShenFenHao());
        chuanYuanChuQinDO.setZhiWei(StringUtils.defaultIfEmpty(shangChuanSavePO.getZhiWei(),""));
        chuanYuanChuQinDO.setJianRenZhiWu(StringUtils.defaultIfEmpty(shangChuanSavePO.getJianRenZhiWu(),""));
        chuanYuanChuQinDO.setRenZhiShuoMing(StringUtils.defaultIfEmpty(shangChuanSavePO.getRenZhiShuoMing(),""));
        chuanYuanChuQinDO.setShangChuanRiQi(shangChuanSavePO.getShangChuanRiQi());
        chuanYuanChuQinDO.setZhuangTai("在船");
        chuanYuanChuQinDO.setShangChuanChuQin(shangChuanChuQin);
        chuanYuanChuQinDO.setXiaChuanChuQin(xiaChuanChuQin);
        chuanYuanChuQinDO.insert();

        /*调配对象更新数据*/
        this.lambdaUpdate()
                .set(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanId,shangChuanChuanYuan.getId())
                .set(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanMing,shangChuanChuanYuan.getXingMing())
                .set(ChuanYuanDiaoPeiDO::getShangChuanCanShu,JSONObject.toJSONString(shangChuanSavePO))
                .set(ChuanYuanDiaoPeiDO::getChuQinId,chuanYuanChuQinDO.getId())
                .set(ChuanYuanDiaoPeiDO::getShangChuanRiQi,DateUtils.stringToDate(shangChuanSavePO.getShangChuanRiQi()))
                .eq(ChuanYuanDiaoPeiDO::getId,id)
                .update();
    }


    /**
     * 调配 - 下船
     */
    @Transactional(rollbackFor = Exception.class)
    public void xiaChuan(ChuanYuanDiaoPeiXiaChuanSavePO xiaChuanSavePO) {
        Long id = xiaChuanSavePO.getId();     //船员调配数据id
        if (id == null) {
            throw new RuntimeException("船员调配数据id不能为空");
        }
        ChuanYuanDiaoPeiDO diaoPeiDO = this.getById(id);
        if (diaoPeiDO == null) {
            throw new RuntimeException("查无此调配数据");
        }
        String shangChuanCanShu = diaoPeiDO.getShangChuanCanShu();
        ChuanYuanDiaoPeiShangChuanSavePO shangChuanSave = new ChuanYuanDiaoPeiShangChuanSavePO();
        if(StringUtils.isNotEmpty(shangChuanCanShu)) {
            shangChuanSave = JSON.parseObject(shangChuanCanShu, ChuanYuanDiaoPeiShangChuanSavePO.class);
        }
        Date shangChuanRiQi = DateUtils.stringToDate(shangChuanSave.getShangChuanRiQi());   //上船日期
        Date xiaChuanRiQi = DateUtils.stringToDate(xiaChuanSavePO.getXiaChuanRiQi());       //下船日期
        if (xiaChuanRiQi.before(shangChuanRiQi)) {
            throw new RuntimeException("船员下船日期["+xiaChuanSavePO.getXiaChuanRiQi()+"]不能早于上船日期["+shangChuanSave.getShangChuanRiQi()+"]");
        }
        Long xinXiId = diaoPeiDO.getXinXiId();
        ChuanBoXinXiDO chuanBoXinXiDO = chuanBoXinXiService.getById(xinXiId);
        String zhongWenMing = chuanBoXinXiDO.getZhongWenMing();                 //船舶中文名
        String shangChuanChuQin = chuanBoXinXiDO.getShangChuanChuQin();         //上船工作时间(天) 出勤
        String xiaChuanChuQin = chuanBoXinXiDO.getXiaChuanChuQin();             //下船当天出勤(天)

        xiaChuanSavePO.setXiaChuanChuQin(xiaChuanChuQin);                       //设置 下船当天出勤
        //结算 船员出勤 数据
        chuanYuanChuQinService.lambdaUpdate()
                .set(ChuanYuanChuQinDO::getXiaChuanRiQi,xiaChuanRiQi)
                .set(ChuanYuanChuQinDO::getZhuangTai,"下船")
                .eq(ChuanYuanChuQinDO::getId,diaoPeiDO.getChuQinId())
                .update();

        //调配对象更新数据
        this.lambdaUpdate()
                .set(ChuanYuanDiaoPeiDO::getLiRenChuanYuanId,diaoPeiDO.getZaiChuanChuanYuanId())
                .set(ChuanYuanDiaoPeiDO::getLiRenChuanYuanMing,diaoPeiDO.getZaiChuanChuanYuanMing())
                .set(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanId,0)
                .set(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanMing,"")
                .set(ChuanYuanDiaoPeiDO::getShangChuanCanShu,"")
                .set(ChuanYuanDiaoPeiDO::getChuQinId,0)
                .eq(ChuanYuanDiaoPeiDO::getId,id)
                .update();

        /* ====================================有无接替人员 没有直接结束==================================== */
        /* ====================================有无接替人员 没有直接结束==================================== */

        if (xiaChuanSavePO.getCunZaiJieTi() == null || xiaChuanSavePO.getCunZaiJieTi() == 0) {
            return;
        }
        //有接替人员
        Long jieTiChuanYuanId = xiaChuanSavePO.getJieTiChuanYuanId();
        ChuanYuanKuDO chuanYuanDO = chuanYuanKuService.getById(jieTiChuanYuanId);
        if (chuanYuanDO == null) {
            throw new RuntimeException("查无此接替船员数据");
        }
        ChuanYuanDiaoPeiDO chuanYuanDiaoPeiDO = this.lambdaQuery()
                .and(w -> {
                    w.eq(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanId, jieTiChuanYuanId)
                            .or()
                            .eq(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId, jieTiChuanYuanId);
                })
                .ne(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId, jieTiChuanYuanId)
                .last(" limit 1 ")
                .one();
        if (chuanYuanDiaoPeiDO != null) {
            String chuanBoMing = chuanYuanDiaoPeiDO.getChuanBoMing();
            String zhiWei = chuanYuanDiaoPeiDO.getZhiWei();
            String zhuangtai = chuanYuanDiaoPeiDO.getZaiChuanChuanYuanId() > 0 ? "任职" : "接替";
            throw new RuntimeException("该接替船员已在船舶:《"+chuanBoMing+"》上的《"+zhiWei+"》职位上进行"+zhuangtai);
        }

        xiaChuanSavePO.setShangChuanChuQin(shangChuanChuQin);                    //设置接替人员 上船当天出勤
        xiaChuanSavePO.setJieTiChuanYuanId(chuanYuanDO.getId());                 //设置 接替人员d
        xiaChuanSavePO.setJieTiChuanYuanMing(chuanYuanDO.getXingMing());         //设置 接替人员名字
        xiaChuanSavePO.setJieTiChuanYuanShenFenHao(chuanYuanDO.getShenFenHao()); //设置 上船船员身份号
        xiaChuanSavePO.setJieTiChuanYuanShouJiHao(chuanYuanDO.getShouJiHao());   //设置 上船船员手机号

        ChuanYuanDiaoPeiShangChuanSavePO shangChuanSavePO = new ChuanYuanDiaoPeiShangChuanSavePO();
        shangChuanSavePO.setShangChuanChuanYuanId(xiaChuanSavePO.getJieTiChuanYuanId());
        shangChuanSavePO.setShangChuanChuanYuanMing(xiaChuanSavePO.getJieTiChuanYuanMing());
        shangChuanSavePO.setZhiWei(diaoPeiDO.getZhiWei());
        shangChuanSavePO.setJianRenZhiWu(xiaChuanSavePO.getJianRenZhiWu());
        shangChuanSavePO.setRenZhiShuoMing(xiaChuanSavePO.getRenZhiShuoMing());
        shangChuanSavePO.setShangChuanRiQi(xiaChuanSavePO.getShangChuanRiQi());
        shangChuanSavePO.setShangChuanChuQin(xiaChuanSavePO.getShangChuanChuQin());
        shangChuanSavePO.setShangChuanGangKou(xiaChuanSavePO.getShangChuanGangKou());
        shangChuanSavePO.setBeiZhu(xiaChuanSavePO.getJieTiBeiZhu());
        shangChuanSavePO.setShangChuanYuanShenFenHao(xiaChuanSavePO.getJieTiChuanYuanShenFenHao());
        shangChuanSavePO.setShangChuanYuanShouJiHao(xiaChuanSavePO.getJieTiChuanYuanShouJiHao());

        //新增 船员出勤 数据
        ChuanYuanChuQinDO chuanYuanChuQinDO = new ChuanYuanChuQinDO();
        chuanYuanChuQinDO.setXinXiId(xinXiId);
        chuanYuanChuQinDO.setChuanBoMing(chuanBoXinXiDO.getZhongWenMing());
        chuanYuanChuQinDO.setChuanYuanId(chuanYuanDO.getId());
        chuanYuanChuQinDO.setChuanYuanMing(chuanYuanDO.getXingMing());
        chuanYuanChuQinDO.setChuanYuanShenFenHao(chuanYuanDO.getShenFenHao());
        chuanYuanChuQinDO.setZhiWei(StringUtils.defaultIfEmpty(shangChuanSavePO.getZhiWei(),""));
        chuanYuanChuQinDO.setJianRenZhiWu(StringUtils.defaultIfEmpty(shangChuanSavePO.getJianRenZhiWu(),""));
        chuanYuanChuQinDO.setRenZhiShuoMing(StringUtils.defaultIfEmpty(shangChuanSavePO.getRenZhiShuoMing(),""));
        chuanYuanChuQinDO.setShangChuanRiQi(shangChuanSavePO.getShangChuanRiQi());
        //chuanYuanChuQinDO.setXiaChuanRiQi(DateUtils.stringToDate(shangChuanSavePO.getJiHuaXiaChuanRiQi()));
        chuanYuanChuQinDO.setZhuangTai("在船");
        chuanYuanChuQinDO.setShangChuanChuQin(shangChuanChuQin);
        chuanYuanChuQinDO.setXiaChuanChuQin(xiaChuanChuQin);
        chuanYuanChuQinDO.insert();

        //调配对象更新数据
        this.lambdaUpdate()
                .set(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanId,chuanYuanDO.getId())
                .set(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanMing,chuanYuanDO.getXingMing())
                .set(ChuanYuanDiaoPeiDO::getShangChuanCanShu,JSONObject.toJSONString(shangChuanSavePO))
                .set(ChuanYuanDiaoPeiDO::getChuQinId,chuanYuanChuQinDO.getId())
                .set(ChuanYuanDiaoPeiDO::getShangChuanRiQi,DateUtils.stringToDate(shangChuanSavePO.getShangChuanRiQi()))

                .set(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId,0)
                .set(ChuanYuanDiaoPeiDO::getJieTiChuanYuanMing,"")
                .set(ChuanYuanDiaoPeiDO::getJieTiCanShu,"")

                .eq(ChuanYuanDiaoPeiDO::getId,id)
                .update();
    }



    /**
     * 接替
     */
    @Transactional(rollbackFor = Exception.class)
    public void jieTi(ChuanYuanDiaoPeiJieTiSavePO jieTiSavePO) {
        Long id = jieTiSavePO.getId();     //船员调配数据id
        if (id == null) {
            throw new RuntimeException("船员调配数据id不能为空");
        }
        ChuanYuanDiaoPeiDO diaoPeiDO = this.getById(id);
        if (diaoPeiDO == null) {
            throw new RuntimeException("查无此调配数据");
        }

        Long xiaRenChuanYuanId = jieTiSavePO.getXiaRenChuanYuanId();//下任船员id
        ChuanYuanKuDO chuanYuanDO = chuanYuanKuService.getById(xiaRenChuanYuanId);
        if (chuanYuanDO == null) {
            throw new RuntimeException("查无此船员数据");
        }

        ChuanYuanDiaoPeiDO chuanYuanDiaoPeiDO = this.lambdaQuery()
                .and(w -> {
                    w.eq(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanId, xiaRenChuanYuanId)
                            .or()
                            .eq(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId, xiaRenChuanYuanId);
                })
                .last(" limit 1 ")
                .one();
        if (chuanYuanDiaoPeiDO != null) {
            String chuanBoMing = chuanYuanDiaoPeiDO.getChuanBoMing();
            String zhiWei = chuanYuanDiaoPeiDO.getZhiWei();
            String zhuangtai = chuanYuanDiaoPeiDO.getZaiChuanChuanYuanId() > 0 ? "任职" : "接替";
            throw new RuntimeException("该接替船员已在船舶:《"+chuanBoMing+"》上的《"+zhiWei+"》职位上进行"+zhuangtai);
        }

        Long xinXiId = diaoPeiDO.getXinXiId();
        ChuanBoXinXiDO chuanBoXinXiDO = chuanBoXinXiService.getById(xinXiId);
        String shangChuanChuQin = chuanBoXinXiDO.getShangChuanChuQin();       //上船工作时间(天) 出勤

        jieTiSavePO.setShangChuanChuQin(shangChuanChuQin);                    //设置 上船当天出勤
        jieTiSavePO.setXiaRenChuanYuanId(chuanYuanDO.getId());                //设置 下任船员id
        jieTiSavePO.setXiaRenChuanYuanMing(chuanYuanDO.getXingMing());        //设置 下任船员名字
        jieTiSavePO.setXiaRenChuanYuanShenFenHao(chuanYuanDO.getShenFenHao());//设置 下任船员身份号
        jieTiSavePO.setXiaRenChuanYuanShouJiHao(chuanYuanDO.getShouJiHao());  //设置 下任船员手机号

        /*调配对象更新数据*/
        this.lambdaUpdate()
                .set(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId,chuanYuanDO.getId())
                .set(ChuanYuanDiaoPeiDO::getJieTiChuanYuanMing,chuanYuanDO.getXingMing())
                .set(ChuanYuanDiaoPeiDO::getJieTiCanShu,JSONObject.toJSONString(jieTiSavePO))
                .eq(ChuanYuanDiaoPeiDO::getId,id)
                .update();
    }


    /**
     * 查看接替详情
     */
    @Override
    public ChuanYuanDiaoPeiJieVO jieTiXiangQing(Long id) {
        if (id == null) {
            throw new RuntimeException("船员调配数据id不能为空");
        }
        ChuanYuanDiaoPeiDO diaoPeiDO = this.getById(id);
        if (diaoPeiDO == null) {
            throw new RuntimeException("查无此调配数据");
        }
        String jieTiCanShu = diaoPeiDO.getJieTiCanShu();
        if (StringUtils.isNotEmpty(jieTiCanShu)) {
            ChuanYuanDiaoPeiJieVO chuanYuanDiaoPeiJieVO = JSON.parseObject(jieTiCanShu, ChuanYuanDiaoPeiJieVO.class);
            chuanYuanDiaoPeiJieVO.setChuanBoMing(diaoPeiDO.getChuanBoMing());
            return chuanYuanDiaoPeiJieVO;
        }
        return null;
    }

    /**
     * 修改接替
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateJieTi(ChuanYuanDiaoPeiJieTiSavePO jieTiSavePO) {
        Long id = jieTiSavePO.getId();     //船员调配数据id
        if (id == null) {
            throw new RuntimeException("船员调配数据id不能为空");
        }
        ChuanYuanDiaoPeiDO diaoPeiDO = this.getById(id);
        if (diaoPeiDO == null) {
            throw new RuntimeException("查无此调配数据");
        }

        Long xiaRenChuanYuanId = jieTiSavePO.getXiaRenChuanYuanId();//下任船员id
        ChuanYuanKuDO chuanYuanDO = chuanYuanKuService.getById(xiaRenChuanYuanId);
        if (chuanYuanDO == null) {
            throw new RuntimeException("查无此船员数据");
        }

        ChuanYuanDiaoPeiDO chuanYuanDiaoPeiDO = this.lambdaQuery()
                .and(w -> {
                    w.eq(ChuanYuanDiaoPeiDO::getZaiChuanChuanYuanId, xiaRenChuanYuanId)
                            .or()
                            .eq(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId, xiaRenChuanYuanId);
                })
                .ne(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId, xiaRenChuanYuanId)
                .last(" limit 1 ")
                .one();
        if (chuanYuanDiaoPeiDO != null) {
            String chuanBoMing = chuanYuanDiaoPeiDO.getChuanBoMing();
            String zhiWei = chuanYuanDiaoPeiDO.getZhiWei();
            String zhuangtai = chuanYuanDiaoPeiDO.getZaiChuanChuanYuanId() > 0 ? "任职" : "接替";
            throw new RuntimeException("该接替船员已在船舶:《"+chuanBoMing+"》上的《"+zhiWei+"》职位上进行"+zhuangtai);
        }

        Long xinXiId = diaoPeiDO.getXinXiId();
        ChuanBoXinXiDO chuanBoXinXiDO = chuanBoXinXiService.getById(xinXiId);
        String shangChuanChuQin = chuanBoXinXiDO.getShangChuanChuQin();       //上船工作时间(天) 出勤
        jieTiSavePO.setShangChuanChuQin(shangChuanChuQin);                    //设置 上船当天出勤
        jieTiSavePO.setXiaRenChuanYuanId(chuanYuanDO.getId());                //设置 下任船员id
        jieTiSavePO.setXiaRenChuanYuanMing(chuanYuanDO.getXingMing());        //设置 下任船员名字
        jieTiSavePO.setXiaRenChuanYuanShenFenHao(chuanYuanDO.getShenFenHao());//设置 下任船员身份号
        jieTiSavePO.setXiaRenChuanYuanShouJiHao(chuanYuanDO.getShouJiHao());  //设置 下任船员手机号

        /*调配对象更新数据*/
        this.lambdaUpdate()
                .set(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId,chuanYuanDO.getId())
                .set(ChuanYuanDiaoPeiDO::getJieTiChuanYuanMing,chuanYuanDO.getXingMing())
                .set(ChuanYuanDiaoPeiDO::getJieTiCanShu,JSONObject.toJSONString(jieTiSavePO))
                .eq(ChuanYuanDiaoPeiDO::getId,id)
                .update();
    }

    /**
     * 删除接替数据
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean delJieTi(Long id){
        return this.lambdaUpdate()
                .set(ChuanYuanDiaoPeiDO::getJieTiChuanYuanId,0)
                .set(ChuanYuanDiaoPeiDO::getJieTiChuanYuanMing,"")
                .set(ChuanYuanDiaoPeiDO::getJieTiCanShu,"")
                .eq(ChuanYuanDiaoPeiDO::getId,id)
                .update();
    }

}
